import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.ticker import PercentFormatter
import warnings  # 新增：导入警告处理模块

# 新增：关闭所有警告
warnings.filterwarnings("ignore")

# 设置中文显示
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题
sns.set_style("whitegrid")  # 设置图表风格


class InsuranceVisualizer:
    """保险业务指标可视化工具类"""

    def __init__(self, data: pd.DataFrame, calculator):
        self.data = data  # 原始数据
        self.calculator = calculator  # 指标计算器实例
        self.periods = data["period"].tolist()  # 所有报告期

    def plot_growth_trend(self, title: str, growth_func, *args, **kwargs):
        """绘制增长率趋势图（适用于各类增长指标）"""
        # 计算各期相对于上一期的增长率
        growth_rates = []
        for i in range(1, len(self.periods)):
            report_period = self.periods[i]
            base_period = self.periods[i - 1]
            rate = growth_func(report_period, base_period, *args, **kwargs)
            growth_rates.append(round(rate, 2))

        # 绘图
        plt.figure(figsize=(10, 6))
        sns.lineplot(x=self.periods[1:], y=growth_rates, marker="o", color="#2c7fb8")
        plt.title(title, fontsize=14)
        plt.xlabel("报告期", fontsize=12)
        plt.ylabel("增长率（%）", fontsize=12)
        plt.gca().yaxis.set_major_formatter(PercentFormatter(xmax=100))  # 百分比显示
        plt.xticks(rotation=45)
        plt.grid(linestyle="--", alpha=0.7)
        plt.tight_layout()
        return plt

    def plot_market_share_comparison(self):
        """绘制市场份额与增量市场份额对比图"""
        # 计算各期市场份额和增量市场份额（增量以首期为基期）
        base_period = self.periods[0]
        market_shares = []
        incremental_shares = []

        for period in self.periods:
            if period == base_period:
                incremental_shares.append(0.0)  # 基期无增量
            else:
                incremental = self.calculator.get_incremental_market_share(period, base_period)
                incremental_shares.append(round(incremental, 2))
            market_share = self.calculator.get_original_market_share(period)
            market_shares.append(round(market_share, 2))

        # 绘图（双轴对比）
        fig, ax1 = plt.subplots(figsize=(10, 6))
        ax2 = ax1.twinx()

        sns.barplot(x=self.periods, y=market_shares, ax=ax1, color="#4292c6", alpha=0.7, label="市场份额")
        sns.lineplot(x=self.periods, y=incremental_shares, ax=ax2, marker="s", color="#fc4e2a", label="增量市场份额")

        ax1.set_title("市场份额与增量市场份额对比", fontsize=14)
        ax1.set_xlabel("报告期", fontsize=12)
        ax1.set_ylabel("市场份额（%）", fontsize=12)
        ax2.set_ylabel("增量市场份额（%）", fontsize=12)
        ax1.yaxis.set_major_formatter(PercentFormatter(xmax=100))
        ax2.yaxis.set_major_formatter(PercentFormatter(xmax=100))

        # 合并图例
        lines1, labels1 = ax1.get_legend_handles_labels()
        lines2, labels2 = ax2.get_legend_handles_labels()
        ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left")

        plt.xticks(rotation=45)
        plt.tight_layout()
        return plt

    def plot_renewal_rate_trend(self):
        """绘制13个月续保率趋势图"""
        renewal_rates = [
            round(self.calculator.get_13_month_renewal_rate(period), 2)
            for period in self.periods
        ]

        plt.figure(figsize=(10, 6))
        sns.barplot(x=self.periods, y=renewal_rates, color="#7fcdbb", alpha=0.8)
        plt.title("13个月续保率趋势", fontsize=14)
        plt.xlabel("报告期", fontsize=12)
        plt.ylabel("续保率（%）", fontsize=12)
        plt.gca().yaxis.set_major_formatter(PercentFormatter(xmax=100))
        plt.xticks(rotation=45)
        # 添加数值标签
        for i, v in enumerate(renewal_rates):
            plt.text(i, v + 0.5, f"{v}%", ha="center", fontsize=10)
        plt.tight_layout()
        return plt

    def plot_agent_efficiency(self):
        """绘制人均保费与件均保费（模拟）对比图"""
        # 计算人均保费
        avg_premiums = [
            round(self.calculator.get_agent_average_premium(period), 2)
            for period in self.periods
        ]

        # 模拟件均保费数据（实际场景中可从calculator获取）
        simulated_case_avg = [2.1, 2.3, 2.5, 2.8, 3.2]  # 单位：万元/件

        # 绘图（双轴）
        fig, ax1 = plt.subplots(figsize=(10, 6))
        ax2 = ax1.twinx()

        sns.lineplot(x=self.periods, y=avg_premiums, ax=ax1, marker="o", color="#2c7fb8", label="人均保费（万元）")
        sns.lineplot(x=self.periods, y=simulated_case_avg, ax=ax2, marker="s", color="#d94801", label="件均保费（万元）")

        ax1.set_title("营销渠道效率指标趋势", fontsize=14)
        ax1.set_xlabel("报告期", fontsize=12)
        ax1.set_ylabel("人均保费（万元）", fontsize=12)
        ax2.set_ylabel("件均保费（万元）", fontsize=12)

        # 合并图例
        lines1, labels1 = ax1.get_legend_handles_labels()
        lines2, labels2 = ax2.get_legend_handles_labels()
        ax1.legend(lines1 + lines2, labels1 + labels2, loc="upper left")

        plt.xticks(rotation=45)
        plt.grid(linestyle="--", alpha=0.5)
        plt.tight_layout()
        return plt

    def plot_risk_metric(self):
        """绘制自留保费占净资产比趋势图"""
        ratios = [
            round(self.calculator.get_retained_premium_to_equity_ratio(period), 2)
            for period in self.periods
        ]

        plt.figure(figsize=(10, 6))
        sns.lineplot(x=self.periods, y=ratios, marker="D", color="#9e2a2b", linewidth=2)
        plt.title("自留保费占净资产比趋势（风险匹配指标）", fontsize=14)
        plt.xlabel("报告期", fontsize=12)
        plt.ylabel("占比（%）", fontsize=12)
        plt.gca().yaxis.set_major_formatter(PercentFormatter(xmax=100))
        plt.xticks(rotation=45)
        # 添加安全阈值参考线（示例：假设阈值为30%）
        plt.axhline(y=30, color="gray", linestyle="--", label="安全阈值（30%）")
        plt.legend()
        plt.grid(linestyle="--", alpha=0.7)
        plt.tight_layout()
        return plt